using System;

namespace KodeIT.Web
{
    /// <summary>
    /// This class represents the event raised by IIS when it is authenticating a user with either anonymous or 
    /// Basic authentication schemes. If your HttpFilter should be notified for this event, it should subscribe 
    /// for the <see cref="IFilterEvents.AuthComplete"/> event.
    /// </summary>
    /// <remarks>
    /// When the server is about to authenticate the client, this event is raised by IIS. The Username and Password 
    /// properties contain the information sent by the client. After handling this event, these values must represent 
    /// a valid Windows user account and password. IIS will then impersonate this account in order to gain 
    /// access to resources. If the authentication method used is integrated Windows authentication, the password 
    /// value will not be available.
    /// </remarks>
    public class AuthenticationEvent : ContextEvent
    {
        private NativeString _username;
        private NativeString _password;

        internal AuthenticationEvent(NativeContext nativeContext)
            : base(nativeContext)
        {
            NativeGetter getter = new NativeGetter(Populate);
            _username = new NativeString(NativeMethods.SF_MAX_USERNAME, getter);
            _password = new NativeString(NativeMethods.SF_MAX_PASSWORD, getter);
        }

        /// <summary>
        /// Gets or sets the username.
        /// </summary>
        public string Username
        {
            get { return _username.Data; }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    throw new ArgumentNullException("value",
                        "The username cannot be null or empty");
                }

                _username.Data = value;
            }
        }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        public string Password
        {
            get { return _password.Data; }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    throw new ArgumentNullException("value", 
                        "The password cannot be null or empty");
                }

                _password.Data = value;
            }
        }

        private void Populate()
        {
            NativeMethods.GetUserPass(NativeContext, _username, _password);
        }

        internal override FilterStatus Update()
        {
            if (_username.Setted || _password.Setted)
            {
                NativeMethods.SetUserPass(
                    NativeContext,
                    _username.Setted ? Username : null,
                    _password.Setted ? Password : null);
            }
            return base.Update();
        }
    }
}
